/**
 * 表单提交提示信息界面，阻止重复提交
 * <p>
 * 设计理念：同一页面，同一时刻，只允许提交一个请求。即完成一次请求，再进行下一次， 提交操作都是单线的。
 * </p>
 */

//--------------------------------------------------------------------------
//
//	初始化
//
//--------------------------------------------------------------------------
var submitter = null;

//页面载入初始化
$( "body" ).ready( function( e )
{
	submitter = new Submitter();
	submitter.init();
} );

//--------------------------------------------------------------------------
//
//	智能提交表单系统类
//
//--------------------------------------------------------------------------

function Submitter()
{
	// 表单提交超时秒数，超过秒数则恢复允许再次提交
	var _timeout = 15;

	//--------------------------------------------------------------------------
	//
	//	属性
	//
	//--------------------------------------------------------------------------

	/**
	 * 设置表单提交时的超时时间
	 * 
	 * @param timeout 超时时间（单位：秒）
	 */
	this.setTimeout = function( timeout )
	{
		if( $.isNumeric( timeout ) )
		{
			_timeout = parseInt( timeout );
		}
	};

	this.getTimeout = function()
	{
		return _timeout;
	};

	this.visible = function()
	{
		return inited() && _mask != null && _mask.visible();
	};

	/**
	 * 是否已经初始化完毕
	 */
	function inited()
	{
		return _mask != null && _content != null;
	}

	//--------------------------------------------------------------------------
	//
	//	初始化
	//
	//--------------------------------------------------------------------------

	var CONST_HTML = "<div id='__FORM_MASK' style='position:fixed;width:100%;height:100%;background-color:#000;filter:alpha(opacity=10);opacity:0.1;'></div>"
			+ "<div id='__FORM_NOTE_CONTENT' style='position:fixed;background:#eee;padding:10px 0 10px;min-height:18px;color:#fff;font-size:18px;text-align:center;line-height:30px;;filter:alpha(opacity=90);opacity:0.9;'><span></span></div>";

	var _mask = null;
	var _content = null;

	this.init = function()
	{
		_mask = $( "#__FORM_MASK" );

		if( !_mask.exist() )
		{
			$( "body" ).append( CONST_HTML );
			_mask = $( "#__FORM_MASK" );
			_content = $( "#__FORM_NOTE_CONTENT" );

			_content.dblclick( this.hide );
		}

		_mask.hide();
		_content.hide();
		_content.html( "" );

		// 绑定事件
		$( window ).resize( { self: this }, function( e )
		{
			var st = e.data.self;

			if( st.visible() )
			{
				st.resize();
			}
		} );
	};

	//--------------------------------------------------------------------------
	//
	//	方法
	//
	//--------------------------------------------------------------------------

	/**
	 * 显示或者隐藏遮罩
	 */
	this.mask = function()
	{
		if( !inited() )
			return;

		this.resize();

		if( !_mask.visible() )
		{
			_mask.fadeIn( 200 );
			_content.fadeIn( 200 );
		}
	};

	/**
	 * 重置调整遮罩大小适应页面
	 */
	this.resize = function()
	{
		var w = $( window ).width();
		var h = $( window ).height();

		_mask.size( w, h );
		_mask.move( 0, 0 );

		_content.width( w );
		_content.move( 0, parseInt( ( h - _content.outerHeight() ) / 2.25 ) );
	};

	/**
	 * 恢复重置为未提交状态
	 */
	this.reset = function()
	{
		if( !inited() )
			return;

		//_mask.fadeOut( 100 );
		_mask.hide();
		_content.hide();
		_content.html( "" );
	};

	this.hide = function()
	{
		if( !inited() )
			return;

		_mask.fadeOut( 100 );
		_content.fadeOut( 100 );
	};

	this.show = function( msg, color )
	{
		this.mask();
		_content.html( msg );
		_content.css( "color", color );
	};

	this.err = function( msg, delay )
	{
		this.show( msg, "#dd0000" );

		if( $.isNumeric( delay ) )
		{
			delay = parseInt( delay );
		}
		else
		{
			delay = 2000;
		}
		setTimeout( this.reset, delay );
	};

	this.msg = function( msg )
	{
		this.show( msg, "#77cc00" );
	};

	this.warn = function( msg )
	{
		this.show( msg, "#cc9900" );
	};

	//--------------------------------------------------------------------------
	//
	//	AJAX 提交模块处理
	//
	//--------------------------------------------------------------------------

	var sets = {};

	/**
	 * 托管提交表单到指定地址
	 * 
	 * @param url 提交地址
	 * @param callback 成功时的回调方法（会传入返回结果作为参数）
	 * @param type 发送请求的类型（get,post 默认使用 post 类型发送请求）
	 * @param dataType 返回数据的类型（将尝试对返回数据进行指定转换，可用值“json(默认),xml,html,text”）
	 */
	this.submit = function( url, data, callback, type, dataType )
	{
		// 默认设置
		sets.context = this;// 供 complete 回调使用
		sets.type = "POST";
		sets.timeout = _timeout * 1000;// 秒数转毫秒
		sets.cache = false;
		sets.url = url;
		sets.data = data;

		// 发送请求的类型
		if( "GET;POST".indexOf( type ) != -1 )
			sets.type = type;

		// 返回结果的类型（默认为纯文本）
		if( "json;xml;html;text".indexOf( dataType ) != -1 )
			sets.dataType = dataType;

		// 成功时的回调方法
		if( $.isFunction( callback ) )
			sets.success = callback;

		// 发生错误时的回调
		sets.error = this.__errorHandler;

		// 其它扩展回调
		//sets.beforeSend = this.__beforeSendHandler;
		//sets.dataFilter = this.__dataFilterHandler;

		// 返回成功后，关闭遮罩
		sets.complete = this.__completeHandler;

		// 发送请求
		this.msg( "正在提交请求..." );
		$.ajax( sets );
	};

	this.get = function( url, data, callback, dataType )
	{
		this.submit( url, data, callback, "GET", dataType );
	};

	this.post = function( url, data, callback, dataType )
	{
		this.submit( url, data, callback, "POST", dataType );
	};

	// beforeSend 在发送请求之前调用，并且传入一个XMLHttpRequest作为参数
	this.__beforeSendHandler = function( http )
	{
		// 发送请求前可修改 XMLHttpRequest 对象的函数，如添加自定义 HTTP 头。XMLHttpRequest 对象是唯一的参数。
		// 这是一个 Ajax 事件。如果返回false可以取消本次ajax请求
		return true;
	};

	// 在请求出错时调用。传入XMLHttpRequest对象，描述错误类型的字符串以及一个异常对象（如果有的话）
	this.__errorHandler = function( http, status )
	{
		// (默认: 自动判断 (xml 或 html)) 请求失败时调用此函数。
		// 有以下三个参数：XMLHttpRequest 对象、错误信息、（可选）捕获的异常对象。
		// 如果发生了错误，错误信息（第二个参数）除了得到null之外，还可能是"timeout", "error", "notmodified" 和 "parsererror"。
		var msg = "";

		switch( status ) {
			case "timeout":
			{
				msg = "由于网络环境问题，提交请求已超时未响应，请稍后重试";
				break;
			}
			case "error":
			{
				msg = "请求发生错误，请稍后重试";
				break;
			}
			case "notmodified":
			{
				msg = "请求结果与没有变化";
				break;
			}
			case "parsererror":
			{
				msg = "解析返回结果时发生错误，请稍后重试";
				break;
			}
			default:
			{
				msg = "请求发生未知错误，请检查";
			}
		}
		this.err( msg );
	};

	// 在请求成功之后调用。传入返回的数据以及"dataType"参数的值。并且必须返回新的数据（可能是处理过的）传递给success回调函数
	this.__dataFilterHandler = function( data, type )
	{
		// 给Ajax返回的原始数据的进行预处理的函数。
		// 提供data和type两个参数：data是Ajax返回的原始数据，type是调用jQuery.ajax时提供的dataType参数。
		// 函数返回的值将由jQuery进一步处理
		return data;
	};

	// 当请求完成之后调用这个函数，无论成功或失败。传入XMLHttpRequest对象，以及一个包含成功或错误代码的字符串
	this.__completeHandler = function( http, status )
	{
		// 请求完成后回调函数 (请求成功或失败之后均调用)。参数： XMLHttpRequest 对象和一个描述成功请求类型的字符串
		if( status == "success" )
		{
			// 请求成功后，重置请求状态
			this.msg( "success..." );
			setTimeout( this.hide, 200 );
		}
	};
}
